import { isObject, def } from '../util/index.js';
import { arrayMethods } from './array.js'
import Dep from './dep.js'
class Observer{
  constructor(value) {
    this.dep = new Dep();
    // 递归增加get和set
    // value.__ob__ = this; 这样写会有递归问题
    def(value, '__ob__', this)
    if(Array.isArray(value)) {
      // 如果是数组的话不需要对索引进行观测 因为会导致性能问题
      // 因为平时也很少 对数组的索引进行操作   
      // 对数组的某一些方法 重写
      // 如果数组里放的是对象我在监控
      value.__proto__ = arrayMethods
      this.observeArray(value)
    }else{
      this.walk(value)
    }
  }
  observeArray(value) {
    for(let i=0; i<value.length; i++) {
      observe(value[i])
    }
  }
  walk(data) {
    let keys = Object.keys(data)
    for(let i = 0; i<keys.length;i++) {
      let key = keys[i];
      let value = data[key];
      defineReactive(data, key, value) // 定义响应式数据
    }
  }
}


function defineReactive(data, key, value) {
  let dep = new Dep()
  let childOb = observe(value); // 这边进行递归  实现深度监听
  Object.defineProperty(data, key, {
    configurable: true,
    enumerable: true,
    get() {
      // console.log('获取了')
      // 取值的时候存起来watcher 
      if(Dep.target) {
        // 
        // window.test.push(dep)
        dep.depend()
        if(childOb) {  // 主要是为了数组 收集到
          // 数组和对象都会收集  但是对象收集的时候会排除一样的watcher
          childOb.dep.depend()

          // 如果数组中还有数组    数组中的数组依赖收集
          if(Array.isArray(value)) {
            dependArray(value)
          }
        }
      }
      return value
    },
    set(newValue) {
      // console.log('设置了')
      if(newValue === value) return 
      // 如果设置的值为对象继续监听
      observe(newValue)
      value = newValue

      dep.notify()
    }
  })
}


function dependArray(value) {
  for(let i = 0; i<value.length; i++) {
    let current = value[i]
    current.__ob__ && current.__ob__.dep.depend()
    if(Array.isArray(current)) {
      dependArray(current)
    }
  }
}

export function observe(data) {

  let isObj = isObject(data)
  if(!isObj) {
    return
  }
  return new Observer(data) // 观测数据
}